﻿#include "UtilityTool.h"
#include <iostream>
#include <format>
#include <Iphlpapi.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "setupapi.lib")

size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

static int getProgressValue(const char* flag, double dt, double dn, double ult, double uln) {
    printf("下载进度:%f\n", dn / dt * 100);
    return 0;
}

long CurlXferinfoCallback(void* ptr, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
    return 0;
}

void HttpClient::AddHeader(const std::string& header) {
    headers = curl_slist_append(headers, header.c_str());
}

void HttpClient::ClearHeaders() {
    if (headers) {
        curl_slist_free_all(headers);
        headers = NULL;
    }
}

bool HttpClient::Get(const std::string& url, std::string& response) {
    //curl初始化  
    CURL* curl = curl_easy_init();
    // curl返回值 
    CURLcode res;
    if (curl)
    {
        //设置curl的请求头
        struct curl_slist* header_list = NULL;
        header_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);

        // 忽略SSL证书检查
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

        //不接收响应头数据0代表不接收 1代表接收
        curl_easy_setopt(curl, CURLOPT_HEADER, 0);

        //设置请求的URL地址 
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

        //设置ssl验证
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);

        //CURLOPT_VERBOSE的值为1时，会显示详细的调试信息
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);

        curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);

        //设置数据接收函数
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&response);
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, getProgressValue);
        curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &CurlXferinfoCallback);

        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

        //设置超时时间
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 6); // set transport and time out time  
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 61);

        // 开启请求  
        res = curl_easy_perform(curl);
    }
    // 释放curl 
    curl_easy_cleanup(curl);
    return (res == CURLE_OK);
}

bool HttpClient::Post(const std::string& url, const std::string& data, std::string& response) {
    if (!m_curl) {
        m_curl = curl_easy_init();
    }

    // set params
    // set curl header
    struct curl_slist* header_list = NULL;
    // der_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
    header_list = curl_slist_append(header_list, "Content-Type:application/json; charset = UTF-8");
    curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, header_list);

    curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(m_curl, CURLOPT_POST, 1L);
    curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, data.c_str());
    curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
    curl_easy_setopt(m_curl, CURLOPT_PROGRESSFUNCTION, getProgressValue);
    curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &response);

    CURLcode res = curl_easy_perform(m_curl);
    return (res == CURLE_OK);
}

std::string HttpClient::Put(const std::string& url, const std::string& data) {
    return PerformRequest("PUT", url, {}, { {"Content-Type", "application/json"} });
}

std::string HttpClient::Delete(const std::string& url) {
    return PerformRequest("DELETE", url, {}, {});
}
bool HttpClient::Encode_url(const std::string& url, std::string& output)
{
    if (!m_curl) {
        m_curl = curl_easy_init();
    }
    char* encoded = curl_easy_escape(m_curl, url.c_str(), url.length());
    output = encoded;
    return true;
}
std::string HttpClient::PerformRequest(const std::string& method, const std::string& url, const std::vector<std::pair<std::string, std::string>>& params, const std::vector<std::pair<std::string, std::string>>& headersList)
{
    CURL* curl_handle = curl_easy_init();
    if (!curl_handle)
    {
        return "";
    }

    // 忽略SSL证书检查
    curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);

    std::string fullUrl = url;
    std::string postData;
    if (!params.empty())
    {
        for (size_t i = 0; i < params.size(); ++i)
        {
            postData += params[i].first + "=" + params[i].second;
            if (i < params.size() - 1)
            {
                postData += "&";
            }
        }
    }



    if (!headersList.empty())
    {
        for (const auto& header : headersList)
        {
            AddHeader(header.first + ": " + header.second);
        }
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
    }

    std::string response;
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &response);
    curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, getProgressValue);
    long http_code = 0;
    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, &CurlXferinfoCallback);
    curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, &http_code);

    CURLcode res = curl_easy_perform(curl_handle);
    if (res != CURLE_OK)
    {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        curl_easy_cleanup(curl_handle);
        ClearHeaders();
        return "";
    }

    curl_easy_cleanup(curl_handle);
    ClearHeaders();

    // 设置请求完成的状态码
    this->m_StatusCode = (res);

    return response;
}


#include <sstream>
#include <iostream>

std::string FormatString(const char* fmt, ...) {
    // ����һ���㹻��Ļ��������洢��ʽ������ַ���  
    // ����Ը���ʵ����Ҫ�����������Ĵ�С  
    const size_t bufferSize = 1024;
    char buffer[bufferSize];

    // ��ʼ��va_list  
    va_list args;
    va_start(args, fmt);

    // ʹ��vsnprintf����ʽ������ַ���д�뻺����  
    // ע�⣺����ʹ��bufferSize - 1��ȷ�����������������������һ��λ�ø�'\0'  
    vsnprintf(buffer, bufferSize - 1, fmt, args);

    // ����va_list��ʹ��  
    va_end(args);

    // ���������е��ַ���ת��Ϊstd::string������  
    return std::string(buffer);
}
#include <filesystem>
std::string GetExeDirectory()
{
    return std::filesystem::current_path().string();
}

void rc4_initialize(std::vector<unsigned char>& s, const std::string& key)
{
    int j = 0;
    for (int i = 0; i < 256; i++)
    {
        s[i] = i;
    }
    for (int i = 0; i < 256; i++)
    {
        j = (j + s[i] + key[i % key.size()]) % 256;
        std::swap(s[i], s[j]);
    }
}


unsigned int RtlComputerCrc32(void* pData, int iLen)
{
    typedef unsigned int(__stdcall* pfnAPI)(int dwInitial, void* pData, int iLen);


    HMODULE tMod = LoadLibraryA("ntdll.dll");
    pfnAPI tProc = (pfnAPI)GetProcAddress(tMod, "RtlComputeCrc32");


    return tProc(0, pData, iLen);
}


std::vector<uint8_t> rc4_encrypt(const std::string& plaintext, const std::string& key)
{
    std::vector<unsigned char> s(256);
    rc4_initialize(s, key);


    std::vector<std::uint8_t> bytes;
    int i = 0, j = 0;


    for (const char c : plaintext)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        std::swap(s[i], s[j]);
        const int rnd = s[(s[i] + s[j]) % 256];
        bytes.push_back(c ^ rnd);
    }


    return bytes;
}


std::string bytes_to_hex_string(const std::vector<uint8_t>& bytes)
{
    std::string str;
    for (const auto& byte : bytes)
    {
        str += std::format("{:02X}", byte);
    }
    //通用_输出调试信息("%lx{}", str);
    return str;
}
#include <fstream>

bool logninTh( std::string& key , std::string& tl_dll)
{

    const HMODULE dll = LoadLibraryA("Helper.dll");
    if (dll == nullptr)
    {
        spdlog::error("Failed to load Helper.dll");
        return false;
    }


    auto control_p = reinterpret_cast<ControlPfn>(GetProcAddress(dll, "Control_P"));
    auto set_port = reinterpret_cast<SetPortfn>(GetProcAddress(dll, "Set_port"));
    auto get_hwid = reinterpret_cast<GetHWIDfn>(GetProcAddress(dll, "GETHWID"));
    auto drv_login = reinterpret_cast<LandingDrvfn>(GetProcAddress(dll, "LandingDrv"));
    auto remove_feature = reinterpret_cast<RemoveFeaturefn>(GetProcAddress(dll, "Remove_feature"));
    auto load_driver = reinterpret_cast<LoadDriverfn>(GetProcAddress(dll, "LoadDriver"));
    auto unload_driver = reinterpret_cast<UnmountDriverfn>(GetProcAddress(dll, "UnmountDriver"));
    auto set_x64_library = reinterpret_cast<Setx64Libraryfn>(GetProcAddress(dll, "Setx64Library"));
    auto insert_driver_list = reinterpret_cast<InsertDriverListfn>(GetProcAddress(dll, "InsertDriverList"));


    control_p(1, 1, "9EC113CF799FF438B1582C2FD682/*/9EC113CF799FF438B15D2C2CDB86/*/9EC112CF7C9AEA27B25F2C2CD385/*/9EC114CF7C9AE227BE44332EDB/*/9EDD17D4609FEE27B75E36", 0, "C:\\Windows", 1, 0);//WAP等于CDN或IP可联系销售获取可绑定自己服务器
    set_port(5555);


    const auto driver_token = "7986A1A5115819HDF827F5B0A1F6D3D9";//自己购买的卡密
    const char* expired_date = drv_login(driver_token, 1, 0);//ABC三个版本差异
    //DebugOutput("expired_date :%s", expired_date);

    remove_feature("", 0, 888);
    load_driver(888);
    get_hwid(888);
    set_x64_library((UINT32)0, 0, 888);
    insert_driver_list("", "TL.exe", 0, "", 888);
    unload_driver(888);
    remove_feature("Helper.dll", 1, 1);
    spdlog::info("绑定游戏名ok");

    unload_driver(1);
    load_driver(1);

    std::string hwid = get_hwid(1);//必须加载驱动后才能取Hwid
    spdlog::info("HWID: {}", hwid);

    HttpClient h;

    //验证卡密
    std::string strSerialNumber;
    GetHardDriveSerialNumber(strSerialNumber);
    std::string MachineID = GetMachineID();
    h.Encode_url(MachineID, MachineID);   
    h.Encode_url(hwid, hwid);
    h.Encode_url(strSerialNumber, strSerialNumber);
    h.Encode_url(key, key);
    auto url = FormatString("http://202.189.9.39:8990/verify_card_secret/?card_key=%s&harddisk_serial_number=%s&mac_address=%s&hwid=%s", key.c_str(), strSerialNumber.c_str(), MachineID.c_str() , hwid.c_str());
    spdlog::info("url: {}", url);
    std::string data;
    std::string jsonString;
    h.Get(url, jsonString);

    std::string message1;;
    utf8_to_mbc(jsonString, message1);

    Json::CharReaderBuilder builder;
    Json::CharReader* reader = builder.newCharReader();
    std::string errors;

    std::string M_ExpirationTime;

    Json::Value root;
    if (!reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.size(), &root, &errors)) {
        spdlog::error("解析失败，错误信息：{}", errors);
    }

    if (!root.isMember("error"))
    {
        std::string message;;
        utf8_to_mbc(root["message"].asString(), message);
        spdlog::error("{} {}", message, key);
        system("pause");
        return false;
    }
    int error = root["error"].asInt();
    if (error)
    {
        std::string message;;
        utf8_to_mbc(root["message"].asString(), message);
        spdlog::error("{} {}", message, key);
        system("pause");
        return false;
    }
    else
    {
        spdlog::info("卡密验证成功");
    }
    utf8_to_mbc(root["card_secret_info"]["M_ExpirationTime"].asString(), M_ExpirationTime);
    std::string data_to_send = root["data_to_send"].asString();
    spdlog::info(data_to_send);

    //const auto User_token1 = "验证卡密";//这里设置你自己验证的卡密而不是驱动的卡密 不能全部用户设置一个 会导致频繁或被封禁
    //const auto User_expired1 = "";//控制驱动列表的有效期 注入时效因此决定 最大6小时 最小5分钟
    const auto Game_Name = "TL.exe";


    //auto crc_checksum = std::format("{}_{}_{}", hwid, User_expired1, User_token1);
    //auto crc_data = RtlComputerCrc32(crc_checksum.data(), crc_checksum.size());//lib kernel32 ntdll windows
    //const std::string data_to_send = bytes_to_hex_string(rc4_encrypt(std::format("{}_{}", crc_checksum, crc_data), "Private"));

    spdlog::info("tl_dll.size:{}" , tl_dll.size());
    set_x64_library((UINT32)(tl_dll.c_str()), tl_dll.size(), 1);//这里才是读入你dll的地方 传递dll byte字节的指针
    insert_driver_list("", Game_Name, 0, data_to_send.data(), 1);//ABC三个版本差异


    spdlog::info("注入dllok-----");
}
#include <fstream>
bool WriteBinaryToFile(const char* filePath, const void* data, size_t size)
{
    std::ofstream file(filePath, std::ios::binary);
    if (!file) {
        std::cerr << "无法打开文件: " << filePath << std::endl;
        return false;
    }
    file.write(reinterpret_cast<const char*>(data), size);
    if (!file) {
        std::cerr << "写入文件失败: " << filePath << std::endl;
        return false;
    }
    return true;
}




void DebugOutput(const char* format, ...) {
    // 使用 va_list 来处理可变参数
    va_list args;
    va_start(args, format);

    // 计算格式化字符串的长度
    int len = vsnprintf(NULL, 0, format, args);
    va_end(args);

    // 分配足够的内存来存储格式化后的字符串
    char* buffer = (char*)malloc(len + 1);
    if (buffer == NULL) {
        return; // 内存分配失败
    }

    // 格式化字符串
    va_start(args, format);
    vsnprintf(buffer, len + 1, format, args);
    va_end(args);

    // 输出调试信息（这里假设输出到控制台）
    printf("%s\n", buffer);

    // 释放内存
    free(buffer);
}


bool DeleteFile(const char* filePath) {
    if (std::remove(filePath) != 0) {
        std::cerr << "删除文件失败: " << filePath << std::endl;
        return false;
    }
    return true;
}

std::string get_python_version() {
    std::string command = "python --version";
    FILE* pipe = _popen(command.c_str(), "r");
    if (!pipe) {
        return "Error opening pipe";
    }

    char buffer[128];
    std::string result = "";
    while (!feof(pipe)) {
        if (fgets(buffer, 128, pipe) != NULL) {
            result += buffer;
        }
    }
    _pclose(pipe);

    // 清理输出中的换行符
    size_t pos = result.find_last_of("\n");
    if (pos != std::string::npos) {
        result.erase(pos);
    }

    return result;
}

//默认MAC地址
std::string GetMachineID() {
    unsigned char mac[6];
    ULONG outBufLen = sizeof(mac);


    // 获取适配器信息
    if (GetAdaptersInfo(nullptr, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
        IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*)malloc(outBufLen);
        if (GetAdaptersInfo(pAdapterInfo, &outBufLen) == NO_ERROR) {
            for (IP_ADAPTER_INFO* pAdapter = pAdapterInfo; pAdapter != nullptr; pAdapter = pAdapter->Next) {
                // 获取第一个有效的 MAC 地址
                memcpy(mac, pAdapter->Address, 6);
                break; // 只取第一个适配器
            }
        }
        free(pAdapterInfo);
    }


    // 将 MAC 地址转换为字符串
    std::ostringstream oss;
    for (int i = 0; i < 6; ++i) {
        oss << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << (int)mac[i];
        if (i < 5) oss << ':'; // 添加分隔符
    }


    return oss.str();
}


#include <winioctl.h>

#define GET_DEVICE_INFO_ERROR -1
#define GET_DEVICE_INFO_OK    0

//默认硬盘序列号
int GetHardDriveSerialNumber(std::string& strSerialNumber)
{
    const char* drive = "\\\\.\\PHYSICALDRIVE0"; // 要获取序列号的硬盘
    HANDLE hDevice = CreateFileA(drive, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);


    if (hDevice == INVALID_HANDLE_VALUE)
    {
        return GET_DEVICE_INFO_ERROR;
    }


    STORAGE_PROPERTY_QUERY storagePropertyQuery;
    ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
    storagePropertyQuery.PropertyId = StorageDeviceProperty;
    storagePropertyQuery.QueryType = PropertyStandardQuery;


    DWORD dwBytesReturned = 0;
    STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader;
    ZeroMemory(&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER));


    if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
        &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
    {
        CloseHandle(hDevice);
        return GET_DEVICE_INFO_ERROR;
    }


    DWORD dwOutBytes;
    BYTE* pOutBuffer = new BYTE[storageDescriptorHeader.Size];
    if (!DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
        pOutBuffer, storageDescriptorHeader.Size, &dwOutBytes, NULL))
    {
        CloseHandle(hDevice);
        delete[] pOutBuffer;
        return GET_DEVICE_INFO_ERROR;
    }


    STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer;
    char* serialNumber = new char[pDeviceDescriptor->SerialNumberOffset + 1];
    memcpy(serialNumber, pOutBuffer + pDeviceDescriptor->SerialNumberOffset, pDeviceDescriptor->SerialNumberOffset);
    serialNumber[pDeviceDescriptor->SerialNumberOffset] = 0;


    strSerialNumber = serialNumber;


    delete[] pOutBuffer;
    delete[] serialNumber;
    CloseHandle(hDevice);
    return GET_DEVICE_INFO_OK;
}


void UtilUTF8ToUnicode(const std::string& utf8Str, std::wstring& outWstr) {
    // 计算所需的宽字符缓冲区大小，包括结尾的 \0  
    int wstrLengthWithNull = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, nullptr, 0);
    if (wstrLengthWithNull > 0) {
        // 实际的字符数不包括结尾的 \0  
        int wstrLength = wstrLengthWithNull - 1;
        // 分配缓冲区  
        outWstr.resize(wstrLength);
        // 执行转换  
        MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &outWstr[0], wstrLengthWithNull);
        // 此时 outWstr 的最后一个字符是 \0，但由于我们不需要它，我们不需要做额外操作  
        // 因为我们已经在 resize 时排除了这个 \0  
    }
    else {
        // 处理错误情况  
        outWstr.clear(); // 清空输出字符串  
    }
}

bool utf8_to_mbc(const std::string& utf8, std::string& mb) {
    // 计算转换所需的缓冲区大小
    int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0);
    if (wideCharSize == 0) {
        return false; // 转换失败
    }


    // 创建宽字符缓冲区
    std::wstring wideString(wideCharSize, L'\0');
    MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &wideString[0], wideCharSize);


    // 计算多字节字符集的大小
    int mbSize = WideCharToMultiByte(CP_ACP, 0, wideString.c_str(), -1, nullptr, 0, nullptr, nullptr);
    if (mbSize == 0) {
        return false; // 转换失败
    }


    // 创建多字节字符集缓冲区
    mb.resize(mbSize);
    WideCharToMultiByte(CP_ACP, 0, wideString.c_str(), -1, &mb[0], mbSize, nullptr, nullptr);


    return true; // 转换成功
}
